mod another_lib;
use another_lib::another_mod;

fn outsider() {
    another_mod::another_fn();
    // 直接跳过文件名的mod(another_lib)
    crate::another_mod::another_fn();
    println!("outsider fn!");
}
pub mod education {

    pub mod lean_rust {
        use std::fmt;

        mod top_level {
            pub fn hi_there() {
                println!("hi there");
            }

            pub mod low_level {
                pub fn hello_world() {
                    println!("hello_world");
                }
            }
        }

        // #[derive(Debug)]
        pub enum PersonId {
            // 括号里是和携带的数据的类型
            Passport(u32),  
            IndentityCard(u32, u32, u32),
        }

        // 输出
        impl fmt::Display for PersonId {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                match self {
                    PersonId::Passport(x) => {
                        write!(f, "{}", x)
                    }
                    PersonId::IndentityCard(x, y, z) => {
                        write!(f, "{} {} {}", x, y, z)
                    }
                }
            }
        }

        pub struct Person {
            pub name: String,
            last_name: String,
            age: u32,
            id: PersonId,
        }

        impl Person {
            // associated function
            // 这种方法适用于构造方法
            pub fn new() -> Person {
                Person {
                    name: "default".to_string(),
                    last_name: "default".to_string(),
                    age: 0,
                    id: PersonId::Passport(123),
                }
            }

            pub fn from(name: String, last_name: String, age: u32, id: PersonId) -> Person {
                Person {
                    name,
                    last_name,
                    age,
                    id,
                }
            }

            pub fn name(&self) -> &String {
                &self.name
            }

            fn display(&self) {
                println!("{} {} {} {}", self.name, self.last_name, self.age, self.id);
            }

            fn change_age(&mut self, new_age: u32) {
                self.age = new_age;
            }
        }
        /*
           感觉类似go的interface

           一组类型的通用接口。
           A trait就像数据类型可以实现的接口。
           当一个类型 实现一个特征，
           可以使用泛型将其抽象地视为该特征 或特质对象。
        */
        pub trait Log {
            fn display_info(&self);
            fn alert_something(&self) {
                println!("Default implementation~~~~~!")
            }
        }

        impl Log for Person {
            fn display_info(&self) {
                super::super::another_mod::another_fn();
                crate::another_mod::another_fn();

                println!("{} {} {} {}", self.name, self.last_name, self.age, self.id);
            }
        }

        pub struct Animal(pub String);

        impl Log for Animal {
            fn display_info(&self) {
                println!("{}", self.0);
            }

            fn alert_something(&self) {
                println!("Animal implementation~~~~~!")
            }
        }

        pub fn log_info(val: impl Log) {
            val.alert_something();
        }

        // 编译之后占空间更小,但是功能比较少
        pub fn log_info_2(val: &dyn Log) {
            val.alert_something();
        }
    }
}
